package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.*;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.AbsChessRoom;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.DateTimeUtil;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.History;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 迷你永恒棋
 */
public class MiniEternalChessRoom extends AbsChessRoom {

    private Sider blackSider; //黑方先手方游戏状态与数据
    private Sider whiteSider; //白方后手方游戏状态与数据
    private CacheSign cacheSign; //缓存标记
    private List<Chess> chessList; //场上棋子集合
    private Chess choose; //当前选中的棋子
    private Chess capture; //当前捕获的棋子
    int[] moveArrow;//移动箭头状态
    int[] putArrow;//放入箭头状态

    public MiniEternalChessRoom(String roomName) {
        super(roomName, "强烈推荐！日出设计的mini永恒棋，双方各有车马炮三种棋子两枚，走入对方禁区获胜，棋盘中有河中石，任何棋子都可以吃，吃完放回各自半区是谓永恒。","迷你永恒棋", Sider.MINI_ETERNAL_CHESS_STYLE, true, true);
        Sider.initChessBoardStyle(this);
    }

    @Override
    public String getRuleText() {
        return "双方在开局前各自布阵；\n" +
                "（后手可以选择交换阵形）\n" +
                "\n" +
                "黑白双方轮流走棋，\n" +
                "若吃子，需立刻将被吃棋子重新打入到被吃棋子所属方的半场\n" +
                "\n" +
                "*在己方禁区的己方棋子获得【无敌】\n" +
                "*己方禁区只能有1枚己方棋子\n" +
                "\n" +
                "车：直线移动任意格，可吃子\n" +
                "马：沿2X3对角移动，可吃子\n" +
                "炮：直线移动任意格，隔「炮台」吃子\n"+
                "\n" +
                "获胜条件：任意己方棋子进入敌方禁区";
    }

    @Override
    protected void doStart() {
        DataManager.noticeAllGameStart(player_black, player_white, roomName);
        overFlag = 1;//重置结束状态：对弈进行中未结束
        playingStartTime = System.currentTimeMillis(); //重置对弈开始时间
        resetGrids(); //先清空棋盘信息
        initSiders();//游戏开始的时候初始化棋子和布局
        initStartCustoms();//分发布局状态按钮
        noticeAllMove(); //开局双方先随机布局
        noticeAllBroadcast("请双方调整初始阵形，修改完成后请点击[布局完成]");
    }

    @Override
    public void resetGrids() {
        step = 0;
        gameTip = "-1";
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        chessList = null;
        choose = null;
        capture = null;
        moveArrow = null;
        putArrow = null;
    }

    @Override
    public void moveLater(Player player, int row, int col) {
        if (player_black != null && player_white != null && player_black == player_white) { //个人模式下
            if (cur == 1) {
                doRule(row, col, 1);
            }
            else if (cur == 2) {
                doRule(row, col, 2);
            }
            else if (cur == 3) { //自由布局阶段
                Chess chess = getChessByPos(row, col); //根据你触摸到的棋子来替换
                if (chess != null) {
                    if (chess.mSide == 1) {
                        doRule(row, col, 1);
                    }
                    else if (chess.mSide == 2) {
                        doRule(row, col, 2);
                    }
                }
            }
        }
        else {//双人模式下
            if (player_black == player) {
                if (cur == 1 || cur == 3) { //3是双方都在自由布局时的阶段
                    doRule(row, col, 1);
                }
            }
            if (player_white == player) {
                if (cur == 2 || cur == 3) {//3是双方都在自由布局时的阶段
                    doRule(row, col, 2);
                }
            }
        }
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (blackSider == null || whiteSider == null) {//异常行为排除掉
            return;
        }
        if (!blackSider.displayFlag && value == 1) {//黑方修改棋子位置
            blackSider.swapOwnChess(getChessByPos(row, col));
            noticeAllRefreshGameInfo();
        }
        else if (!whiteSider.displayFlag && value == 2) {//白方修改棋子位置
            whiteSider.swapOwnChess(getChessByPos(row, col));
            noticeAllRefreshGameInfo();
        }
        else {//正常对弈时
            if (value == 1) { //黑方点击
                if (capture != null) { //持有棋子要先打入
                    List<Integer> ids = getCaptureCanPutIndexes();
                    for (Integer id : ids) {
                        if (getIndex(row, col) == id) {
                            doChessPut(row, col); //执行棋子放下效果
                            noticeWhiteMove();
                        }
                    }
                }
                else if (choose == null || choose.mSide != 1) { //黑方还未选择目标时
                    Chess chess = getChessByPos(row, col);
                    if (chess != null && chess.mSide == 1) {
                        putArrow = null; //切换方向选中时就要清除箭头状态
                        moveArrow = null; //以免标记太多碍眼
                        choose = chess;//选中己方棋子
                        noticeAllRefreshGameInfo(); //仅仅刷新显示，黑方还能继续点击
                    }
                }
                else { //已经选中黑方棋子了
                    if (choose.isPosCanMove(row, col, this, curGrids, chessList)) { //可以移动到目标位置
                        //移动判定
                        if (isRivalHome(1, getIndex(row, col))) { //黑棋进入对方禁区
                            doChessMove(row, col);//执行移动操作
                            doOver(WinMode.BLACK_WIN,player_black.getNickNameOrTemp() + "执黑获胜！");
                        }
                        else {
                            //吃子判定
                            Chess chess = getChessByPos(row, col);
                            doChessMove(row, col);//执行移动操作
                            if (chess != null) {
                                chessList.remove(chess); //暂时先从列表中移除，避免判定和绘制干扰
                                if (chess instanceof Stone) { //河中石头直接吃掉，否则要持住
                                    noticeWhiteMove();
                                }
                                else {
                                    capture = chess; //持拘
                                    noticeAllRefreshGameInfo(); //仅仅刷新显示，黑方还能继续点击
                                }
                            }
                            else {
                                noticeWhiteMove();
                            }
                        }
                    }
                    else { //目标位置不能移动到
                        Chess chess = getChessByPos(row, col);
                        if (chess != null && chess.mSide == 1) {
                            choose = chess;//切换选中己方棋子
                            noticeAllRefreshGameInfo(); //仅仅刷新显示，还能继续点击
                        }
                        else {
                            choose = null;
                            noticeAllRefreshGameInfo(); //仅仅刷新显示，还能继续点击
                        }
                    }
                }
            }
            else if (value == 2) { //白方点击
                if (capture != null) { //持有棋子要先打入
                    List<Integer> ids = getCaptureCanPutIndexes();
                    for (Integer id : ids) {
                        if (getIndex(row, col) == id) {
                            doChessPut(row, col);
                            noticeBlackMove();
                        }
                    }
                }
                else if (choose == null || choose.mSide != 2) { //白方没有选中棋子时
                    Chess chess = getChessByPos(row, col);
                    if (chess != null && chess.mSide == 2) {
                        putArrow = null; //切换方向选中时就要清除箭头状态
                        moveArrow = null; //以免标记太多碍眼
                        choose = chess;
                        noticeAllRefreshGameInfo();
                    }
                }
                else {//已经选中白方棋子了
                    if (choose.isPosCanMove(row, col, this, curGrids, chessList)) {//可以移动到目标位置
                        //执行移动操作
                        if (isRivalHome(2, getIndex(row, col))) { //白棋进入对方禁区
                            doChessMove(row, col);//执行移动操作
                            doOver(WinMode.WHITE_WIN,player_white.getNickNameOrTemp() + "执白获胜！");
                        }
                        else {
                            Chess chess = getChessByPos(row, col);
                            doChessMove(row, col);//执行移动操作
                            if (chess != null) {
                                chessList.remove(chess); //暂时先从列表中移除，避免判定和绘制干扰
                                if (chess instanceof Stone) { //河中石头直接吃掉，否则要持住
                                    noticeBlackMove();
                                }
                                else {
                                    capture = chess; //持拘
                                    noticeAllRefreshGameInfo(); //仅仅刷新显示，黑方还能继续点击
                                }
                            }
                            else {
                                noticeBlackMove();
                            }
                        }
                    }
                    else { //目标位置不能移动到
                        Chess chess = getChessByPos(row, col);
                        if (chess != null && chess.mSide == 2) {
                            choose = chess; //切换选中己方棋子
                            noticeAllRefreshGameInfo(); //仅仅刷新显示，还能继续点击
                        }
                        else {
                            choose = null;
                            noticeAllRefreshGameInfo(); //仅仅刷新显示，白方还能继续点击
                        }
                    }
                }
            }
        }
    }

    //执行棋子放入操作
    private void doChessPut(int row, int col) {
        int oRow = capture.pRow;
        int oCol = capture.pCol;
        putArrow = new int[]{getIndex(capture.pRow, capture.pCol), getIndex(row, col), capture.mSide};
        capture.pCol = col;
        capture.pRow = row;
        chessList.add(capture);
        addPutHistory(capture, oRow, oCol, row, col);
        capture = null;
    }

    //执行棋子移动操作
    private void doChessMove(int row, int col) {
        int oRow = choose.pRow;
        int oCol = choose.pCol;
        moveArrow = new int[]{getIndex(choose.pRow, choose.pCol), getIndex(row, col), choose.mSide};
        choose.pRow = row;
        choose.pCol = col;
        stepAdd();;
        addMoveHistory(choose, oRow, oCol, row, col);
        choose = null;
    }

    @Override
    protected void preHistory() {
        boolean isPersonal = (player_black == player_white); //是否个人模式
        if (isSaveHistoryToFile && !isPersonal) {
            history = new History();
            String dataTime = DateTimeUtil.localDateTimeToStr(LocalDateTime.now(), DateTimeUtil.ALL_FORMAT);
            String names = getBlackPlayerName() + "(黑)" + "-" + getWhitePlayerName() + "(白)";
            String gameInfo = "====开始====";
            String gridStr = formatGrids();
            history.add(dataTime + "\n" + names + "\n" + gameInfo + "\n" + gridStr + "\n");
            System.out.println(roomName + "准备开始记录战报：" + names);
        }
        else {
            history = null;
        }
    }

    private void addPutHistory(Chess chess, int oRow, int oCol, int nRow, int nCol) {
        if (isSaveHistoryToFile && history!=null){
            String dataTime = DateTimeUtil.localDateTimeToStr(LocalDateTime.now(), DateTimeUtil.ALL_FORMAT);
            String names = getBlackPlayerName() + "(黑)" + "-" + getWhitePlayerName() + "(白)";
            String actionStr = (chess.mSide == 1 ? "黑" : "白") + chess.getRecordName() + "从" + (oRow + 1) + (char) (97 + oCol) + "被放到" + (nRow + 1) + (char) (97 + nCol);
            String gridStr = formatGrids();
            history.add(dataTime + "\n" + names + "\n" + actionStr + "\n" + gridStr + "\n");
        }

    }

    private void addMoveHistory(Chess chess, int oRow, int oCol, int nRow, int nCol) {
        if (isSaveHistoryToFile && history!=null){
            String dataTime = DateTimeUtil.localDateTimeToStr(LocalDateTime.now(), DateTimeUtil.ALL_FORMAT);
            String names = getBlackPlayerName() + "(黑)" + "-" + getWhitePlayerName() + "(白)";
            String actionStr = "第" + step + "步," + (chess.mSide == 1 ? "黑" : "白") + chess.getRecordName() + "从" + (oRow + 1) + (char) (97 + oCol) + "移动到" + (nRow + 1) + (char) (97 + nCol);
            String gridStr = formatGrids();
            history.add(dataTime + "\n" + names + "\n" + actionStr + "\n" + gridStr + "\n");
        }
    }

    // 以格式化方式输出棋盘
    private String formatGrids() {
        int row = curGrids.length;
        int col = curGrids[0].length;
        StringBuilder gridStr = new StringBuilder();
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                String recordStr = getRecordStrByPos(i, j);
                gridStr.append(recordStr);
                gridStr.append(" ");
            }
            gridStr.append("\n");
        }
        return gridStr.toString();
    }

    // 格式化输出棋盘时获取每个位置的格式化文字
    private String getRecordStrByPos(int row, int col) {
        String tempStr = "空";
        int index = getIndex(row, col);
        if (index == blackSider.homeStart || index == blackSider.homeEnd || index == whiteSider.homeStart || index == whiteSider.homeEnd) {
            tempStr = "禁";
        }
        if (row == (blackSider.campEnd / curGrids.length + 1)) { //黑方半场末尾的下一行是河
            tempStr = "河";
        }
        for (Chess chess : chessList) {
            if (chess.pRow == row && chess.pCol == col) {
                return chess.getRecordName();
            }
        }
        return tempStr;
    }

    @Override
    public String getGameInfo() {
        //先全部初始化
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        signList.add(cacheSign);

        //根据chessList集合和choose对象来生成要显示到客户端的布局和标记
        if (chessList != null && chessList.size() > 0) {
            //绘制棋子
            for (Chess chess : chessList) {
                curGrids[chess.pRow][chess.pCol] = chess.mSide; //显示棋子的底座
                signList.add(new TextSign(getIndex(chess.pRow, chess.pCol), chess.mName, chess.getColor())); //显示棋子的文字
            }

            //绘制对弈时的选中棋子移动状态
            if (choose != null) {
                //绘制棋子可移动路径
                List<int[]> canMovedPosList = choose.getCanMovedPos(this, curGrids, chessList); //获取该棋子可移动到的格子的坐标集合
                if (canMovedPosList != null && canMovedPosList.size() > 0) {
                    List<Integer> ids = new ArrayList<>();
                    for (int[] canMovedPos : canMovedPosList) {
                        ids.add(getIndex(canMovedPos[0], canMovedPos[1]));
                    }
                    signList.add(new ColorSign(ids, "#9988EE88")); //可移动到的格子用更淡的绿色表示
                }
                //绘制棋子选中状态
                signList.add(new GroundSign(getIndex(choose.pRow, choose.pCol), "#00FFFFFF", "#FF33CC33", 2F, 0, 1));
            }

            //绘制对弈时的持拘状态
            if (capture != null) {
                //绘制持拘棋子，以角标的形式显示在原位置格子左上角
                String bgColor = capture.mSide == 1 ? ColorCost.DETAINED_BADGE_WHITE : ColorCost.DETAINED_BADGE_BLACK;
                signList.add(new BadgeSign(getIndex(capture.pRow, capture.pCol), capture.mName, 2, capture.getColor(), bgColor));
                //绘制显示可放入范围
                List<Integer> ids = getCaptureCanPutIndexes();
                signList.add(new ColorSign(ids, "#9966EE66"));
            }

            //绘制对弈时的箭头标记
            if (moveArrow != null && moveArrow.length == 3) {
                signList.add(new LineSign(moveArrow[0], moveArrow[1], moveArrow[2] == 1 ? "#99EE6666" : "#996666EE", 1));
            }
            if (putArrow != null && putArrow.length == 3) {
                signList.add(new LineSign(putArrow[0], putArrow[1], putArrow[2] == 1 ? "#99EE6666" : "#996666EE", 1));
            }

            //绘制布局时的选中状态
            if (blackSider != null && !blackSider.displayFlag && blackSider.swapTarget != null) {
                List<Integer> ins = new ArrayList<>();
                ins.add(getIndex(blackSider.swapTarget.pRow, blackSider.swapTarget.pCol));
                signList.add(new AroundSign(ins, "#00FFFFFF", "#FF33AA33", 1.5f));
            }
            if (whiteSider != null && !whiteSider.displayFlag && whiteSider.swapTarget != null) {
                List<Integer> ins = new ArrayList<>();
                ins.add(getIndex(whiteSider.swapTarget.pRow, whiteSider.swapTarget.pCol));
                signList.add(new AroundSign(ins, "#00FFFFFF", "#FF33AA33", 1.5f));
            }
        }
        return super.getGameInfo();
    }

    @Override
    public String getCoordMode() {
        return "41410000";
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        return cacheSign;
    }

    //初始化对弈双方的元数据
    private void initSiders() {
        blackSider = new Sider(1);
        whiteSider = new Sider(2);
        chessList = new ArrayList<>();
        Sider.displayStone(chessList);
        blackSider.randomDisplay(chessList);
        whiteSider.randomDisplay(chessList);
        choose = null;
    }

    //分发布局状态的按钮
    private void initStartCustoms() {
        if (player_black != null && player_white != null && player_black == player_white) { //个人模式下发按钮的逻辑
            player_black.registerCustomBottom(
                    new CustomBottom(this, "随机布局", player -> {
                        //再重新生成布局
                        blackSider.randomDisplay(chessList);
                        whiteSider.randomDisplay(chessList);
                        noticeAllRefreshGameInfo();//通知界面刷新
                    }),
                    new CustomBottom(this, "布局完成", player -> {
                        //单人模式不需要交换规则直接就通知开始
                        blackSider.completeDisplay();
                        whiteSider.completeDisplay();
                        noticeAllBroadcast("布局完成可选择棋子移动");
                        player_black.clearCustomBottom();
                        player_black.dispatchCustomBottom();
                        noticeBlackMove(); //然后黑方先手落子
                        preHistory(); //准备记录日志
                    })
            );
        }
        else { //双人模式下发按钮的逻辑
            if (player_black != null) {
                player_black.registerCustomBottom(
                        new CustomBottom(this, "随机布局", player -> {
                            blackSider.randomDisplay(chessList);//再重新生成布局
                            noticeAllRefreshGameInfo();//通知界面刷新
                        }),
                        new CustomBottom(this, "布局完成", player -> {
                            //黑方布局完成就暂停操作
                            blackSider.completeDisplay();
                            player_black.clearCustomBottom();
                            player_black.dispatchCustomBottom();
                            //判断白方是否也布局完成了
                            if (whiteSider.displayFlag) {
                                initChangeLayoutCustoms(); //后手方选择是否交换布局
                                noticeNoMove();//双方都不能再修改棋子位置了
                                /*noticeAllBroadcast("黑方开始选择棋子移动");
                                player_white.clearCustomBottom();
                                player_white.dispatchCustomBottom();
                                noticeBlackMove();*/
                            }
                            else {
                                noticeWhiteMove(); //白方继续能修改棋子位置
                            }
                        })
                );
            }
            if (player_white != null) {
                player_white.registerCustomBottom(
                        new CustomBottom(this, "随机布局", player -> {
                            whiteSider.randomDisplay(chessList);//再重新生成布局
                            noticeAllRefreshGameInfo();//通知界面刷新
                        }),
                        new CustomBottom(this, "布局完成", player -> {
                            whiteSider.completeDisplay();
                            player_white.clearCustomBottom();
                            player_white.dispatchCustomBottom();
                            if (blackSider.displayFlag) {
                                initChangeLayoutCustoms();
                                noticeNoMove();//双方都不能再修改棋子位置了
                                /*noticeAllBroadcast("黑方开始选择棋子移动");
                                player_white.clearCustomBottom();
                                player_white.dispatchCustomBottom();
                                noticeBlackMove();*/
                            }
                            else {
                                noticeBlackMove();
                            }
                        })
                );
            }
        }
    }

    //分发交换状态下的按钮
    private void initChangeLayoutCustoms() {
        noticeAllBroadcast("白方选择是否交换布局？");
        player_white.registerCustomBottom(
                new CustomBottom(this, "交换布局", player1 -> {
                    Sider.swapLayout(chessList);
                    noticeAllBroadcast("黑方开始选择棋子移动");
                    player_white.clearCustomBottom();
                    player_white.dispatchCustomBottom();
                    noticeBlackMove();
                }),
                new CustomBottom(this, "直接开始", player12 -> {
                    noticeAllBroadcast("黑方开始选择棋子移动");
                    player_white.clearCustomBottom();
                    player_white.dispatchCustomBottom();
                    noticeBlackMove();
                    preHistory(); //准备记录日志
                })
        );
    }


    /**
     * 根据坐标搜索棋子
     */
    private Chess getChessByPos(int row, int col) {
        for (Chess chess : chessList) {
            if (chess.pRow == row && chess.pCol == col) {
                return chess;
            }
        }
        return null;
    }

    /**
     * 己方禁区是否已经有棋子了
     */
    private boolean isOwnHomeHadChess(int mSide) {
        if (mSide == 1) {
            int[] posA = getPositionByIndex(blackSider.homeStart);
            if (curGrids[posA[0]][posA[1]] == 1) {
                return true;
            }
            int[] posB = getPositionByIndex(blackSider.homeEnd);
            if (curGrids[posB[0]][posB[1]] == 1) {
                return true;
            }
        }
        else if (mSide == 2) {
            int[] posA = getPositionByIndex(whiteSider.homeStart);
            if (curGrids[posA[0]][posA[1]] == 2) {
                return true;
            }
            int[] posB = getPositionByIndex(whiteSider.homeEnd);
            if (curGrids[posB[0]][posB[1]] == 2) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否己方禁区
     */
    private boolean isOwnHome(int side, int index) {
        if (side == 1) {
            return blackSider.homeStart == index || blackSider.homeEnd == index;
        }
        else if (side == 2) {
            return whiteSider.homeStart == index || whiteSider.homeEnd == index;
        }
        else {
            return false;
        }
    }

    /**
     * 是否对方禁区
     */
    private boolean isRivalHome(int side, int index) {
        if (side == 1) {
            return whiteSider.homeStart == index || whiteSider.homeEnd == index;
        }
        else if (side == 2) {
            return blackSider.homeStart == index || blackSider.homeEnd == index;
        }
        else {
            return false;
        }
    }

    /**
     * 获取持拘棋子可以放入的位置
     */
    private List<Integer> getCaptureCanPutIndexes() {
        List<Integer> ids = new ArrayList<>();
        int w = curGrids[0].length;
        if (capture.mSide == 1) {
            for (int i = blackSider.campStart; i <= blackSider.campEnd; i++) {
                int col = i % w;
                int row = i / w;
                if (curGrids[row][col] == 0) {
                    ids.add(i);
                }
            }
        }
        else if (capture.mSide == whiteSider.side) {
            for (int i = whiteSider.campStart; i <= whiteSider.campEnd; i++) {
                int col = i % w;
                int row = i / w;
                if (curGrids[row][col] == 0) {
                    ids.add(i);
                }
            }
        }
        if (isOwnHomeHadChess(capture.mSide)) { //如果禁区里已经有棋子了，就不能再打入
            ids.removeIf(integer -> integer == blackSider.homeStart || integer == whiteSider.homeStart || integer == blackSider.homeEnd || integer == whiteSider.homeEnd);
        }
        return ids;
    }


    /**
     * 对弈双方的各种信息
     */
    private static class Sider {

        //棋盘模板
        public static final int[][] MINI_ETERNAL_CHESS_STYLE = {
                {0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0}
        };

        private int side = 0;//归属黑棋还是白棋 1黑  2白
        private int campStart, campEnd; //半场范围
        private int homeStart, homeEnd; //禁区范围
        private int[] stationPoints; //初始点格子索引
        private Chess swapTarget; //准备交换的目标
        private boolean displayFlag; //布局状态，布局完成转为true

        public Sider(int side) {
            this.side = side;
            this.displayFlag = false;
            divideSiderArea();
        }

        /**
         * 给对弈双方划分区域
         */
        public void divideSiderArea() {
            if (this.side == 1) {
                this.campStart = 0;
                this.campEnd = 17;
                this.homeStart = 2;
                this.homeEnd = 3;
                this.stationPoints = new int[]{1, 4, 6, 7, 10, 11};
            }
            else if (this.side == 2) {
                this.campStart = 24;
                this.campEnd = 41;
                this.homeStart = 38;
                this.homeEnd = 39;
                this.stationPoints = new int[]{30, 31, 34, 35, 37, 40};
            }
        }

        /**
         * 双方随机布局
         */
        public void randomDisplay(List<Chess> chessList) {
            chessList.removeIf(chess -> chess.mSide == side);//清除旧棋子
            swapTarget = null; //记得先清空，否则数据非原来的了
            List<Chess> tempChess = new ArrayList<>(); //先把对象创建出来
            tempChess.add(new Chariot(side, 0, 0));
            tempChess.add(new Chariot(side, 0, 0));
            tempChess.add(new Horse(side, 0, 0));
            tempChess.add(new Horse(side, 0, 0));
            tempChess.add(new Cannon(side, 0, 0));
            tempChess.add(new Cannon(side, 0, 0));
            Collections.shuffle(tempChess); //随机乱序，然后按顺序排到出生点
            for (int i = 0; i < tempChess.size(); i++) {
                Chess chess = tempChess.get(i);
                int index = stationPoints[i];
                int colNum = MINI_ETERNAL_CHESS_STYLE[0].length;
                chess.pRow = index / colNum;
                chess.pCol = index % colNum;
            }
            chessList.addAll(tempChess); //最后再放到公共的棋子容器里
        }

        /**
         * 交换己方两个棋子的位置
         */
        public void swapOwnChess(Chess target) {
            if (target == null) {
                return;
            }
            if (target.mSide == side) {
                if (swapTarget == null) {
                    swapTarget = target;
                }
                else {
                    int tempCol = swapTarget.pCol;
                    int tempRow = swapTarget.pRow;
                    swapTarget.pRow = target.pRow;
                    swapTarget.pCol = target.pCol;
                    target.pRow = tempRow;
                    target.pCol = tempCol;
                    swapTarget = null;
                }
            }
        }

        /**
         * 完成布局修改状态
         */
        public void completeDisplay() {
            displayFlag = true;
            swapTarget = null;
        }

        /**
         * 初始化棋盘样式
         */
        public static void initChessBoardStyle(MiniEternalChessRoom room) {
            room.originGrids = MINI_ETERNAL_CHESS_STYLE;
            room.curGrids = GridsUtils.copyGrids(room.originGrids);
            List<Sign> chessboardStyle = new ArrayList<>();
            int row = room.curGrids.length;
            int col = room.curGrids[0].length;
            //绘制类似国际象棋的黑白相间的格子
            List<Integer> bGrids = new ArrayList<>();
            List<Integer> wGrids = new ArrayList<>();
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    int index = room.getIndex(i, j);
                    if ((i + j) % 2 == 0) {
                        bGrids.add(index);
                    }
                    else {
                        wGrids.add(index);
                    }
                }
            }
            chessboardStyle.add(new ColorSign(bGrids, "#FF888888"));
            chessboardStyle.add(new ColorSign(wGrids, "#FFDDDDDD"));
            //画棕色外边框
            chessboardStyle.add(new GroundSign(room.getIndex(0, 0), room.getIndex(6, 5), "#00000000", "#FFAA6622", 2.2f, 0, 0));
            //画河道边框
            chessboardStyle.add(new GroundSign(room.getIndex(3, 0), room.getIndex(3, 5), "#00000000", "#FFAA6622", 1.3f, 0, 0));

            //绘制双边禁区
            chessboardStyle.add(new GroundSign(room.getIndex(0, 2), room.getIndex(0, 3), "#00000000", "#FFEE6666", 2f, 0, 1));
            chessboardStyle.add(new GroundSign(room.getIndex(6, 2), room.getIndex(6, 3), "#00000000", "#FF6666EE", 2f, 0, 1));
            //将背景封装为缓存标记
            room.cacheSign = new CacheSign(room,"background",1,true,chessboardStyle); //*** 修改背景样式记得改这里的版本号！！！
        }


        /**
         * 初始摆放河中石
         */
        public static void displayStone(List<Chess> chessList) {
            chessList.add(new Stone(3, 0));
            chessList.add(new Stone(3, 1));
            chessList.add(new Stone(3, 2));
            chessList.add(new Stone(3, 3));
            chessList.add(new Stone(3, 4));
            chessList.add(new Stone(3, 5));
        }

        /**
         * 交换布局
         */
        public static void swapLayout(List<Chess> chessList) {
            for (Chess chess : chessList) {
                //交换归属权
                if (chess.mSide == 1) {
                    chess.mSide = 2;
                }
                else if (chess.mSide == 2) {
                    chess.mSide = 1;
                }
                chess.pRow = 6 - chess.pRow; //棋子纵坐标根据河道位置翻转
            }
        }

    }

    /**
     * 棋子基类
     */
    private abstract static class Chess {
        String mName; //棋子简名
        int mSide; //归属黑棋还是白棋 1黑  2白  9中立
        int pRow; //在棋盘上的横坐标
        int pCol; //在棋盘上的纵坐标

        public Chess(String name, int mSide, int pRow, int pCol) {
            this.mName = name;
            this.mSide = mSide;
            this.pRow = pRow;
            this.pCol = pCol;
        }

        public String getColor() {
            if (mSide == 1) {
                return "#FFEE6666";
            }
            else if (mSide == 2) {
                return "#FF6666EE";
            }
            else {
                return "#FFEEEE66";
            }
        }

        //公共移动限制
        protected boolean generalMoveLimit(int row, int col, MiniEternalChessRoom room, int[][] curGrids) {
            if (row == pRow && col == pCol) { //不能停留在原地
                return false;
            }
            if (room.isRivalHome(mSide, room.getIndex(row, col)) && curGrids[row][col] != 0) { //地方禁区里的棋子不能吃
                return false;
            }
            if (room.isOwnHome(mSide, room.getIndex(row, col))) {
                if (curGrids[row][col] != 0) { //己方禁区里的棋子不能吃
                    return false;
                }
                else if (room.isOwnHomeHadChess(mSide)) { //己方禁区里已经有棋子了
                    return room.isOwnHome(mSide, room.getIndex(pRow, pCol)); //如果那个棋子是自己本身就可以移动，否则不能再进入了
                }
            }
            return true; //其它情况都能走
        }

        //获取可移动范围列表
        public List<int[]> getCanMovedPos(MiniEternalChessRoom room, int[][] curGrids, List<Chess> chessList) {
            List<int[]> canMovedPosList = new ArrayList<>();
            int h = curGrids.length;
            int w = curGrids[0].length;
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    if (isPosCanMove(i, j, room, curGrids, chessList)) {
                        canMovedPosList.add(new int[]{i, j});
                    }
                }
            }
            return canMovedPosList;
        }

        //个性化的移动算法
        public abstract boolean isPosCanMove(int row, int col, MiniEternalChessRoom room, int[][] curGrids, List<Chess> chessList);

        public abstract String getRecordName();
    }

    /**
     * 车
     */
    private static class Chariot extends Chess {

        public Chariot(int mSide, int pRow, int pCol) {
            super("车", mSide, pRow, pCol);
        }

        @Override
        public boolean isPosCanMove(int row, int col, MiniEternalChessRoom room, int[][] curGrids, List<Chess> chessList) {
            if (row != pRow && col != pCol) { //非直线范围不能移动
                return false;
            }
            if (row == pRow) { //横向移动时
                if (col > pCol) { //向右移动时
                    for (int i = 1; i < col - pCol; i++) {
                        if (curGrids[row][pCol + i] != 0) { //不能越过其它棋子（但阻挡得棋子可以走到）
                            return false;
                        }
                    }
                }
                else if (col < pCol) { //向左移动时
                    for (int i = 1; i < pCol - col; i++) {
                        if (curGrids[row][col + i] != 0) {//不能越过其它棋子（但阻挡得棋子可以走到）
                            return false;
                        }
                    }
                }
            }
            if (col == pCol) { //纵向移动时
                if (row > pRow) { //向下移动时
                    for (int i = 1; i < row - pRow; i++) {
                        if (curGrids[pRow + i][col] != 0) { //不能越过其它棋子（但阻挡得棋子可以走到）
                            return false;
                        }
                    }
                }
                else if (row < pRow) { //向上移动时
                    for (int i = 1; i < pRow - row; i++) {
                        if (curGrids[row + i][col] != 0) { //不能越过其它棋子（但阻挡得棋子可以走到）
                            return false;
                        }
                    }
                }
            }
            return generalMoveLimit(row, col, room, curGrids);
        }

        @Override
        public String getRecordName() {
            return mSide == 1 ? "車" : mName;
        }
    }

    /**
     * 马
     */
    private static class Horse extends Chess {

        public Horse(int mSide, int pRow, int pCol) {
            super("马", mSide, pRow, pCol);
        }

        @Override
        public boolean isPosCanMove(int row, int col, MiniEternalChessRoom room, int[][] curGrids, List<Chess> chessList) {
            int h = Math.abs(row - pRow);
            int w = Math.abs(col - pCol);
            if (h == 1 && w == 2 || h == 2 && w == 1) {
                return generalMoveLimit(row, col, room, room.curGrids);
            }
            else {
                return false;
            }
        }

        @Override
        public String getRecordName() {
            return mSide == 1 ? "馬" : mName;
        }
    }

    /**
     * 炮
     */
    private static class Cannon extends Chess {

        public Cannon(int mSide, int pRow, int pCol) {
            super("炮", mSide, pRow, pCol);
        }

        @Override
        public boolean isPosCanMove(int row, int col, MiniEternalChessRoom room, int[][] curGrids, List<Chess> chessList) {
            if (row != pRow && col != pCol) { //非直线范围不能移动
                return false;
            }
            int count = 0; //记录路径上遇到的棋子数量
            if (row == pRow) { //横向移动时
                if (col > pCol) { //向右移动时
                    for (int i = pCol; i <= col; i++) {
                        if (curGrids[row][i] != 0) {
                            count++;
                        }
                    }
                }
                else if (col < pCol) { //向左移动时
                    for (int i = col; i <= pCol; i++) {
                        if (curGrids[row][i] != 0) {
                            count++;
                        }
                    }
                }
            }
            if (col == pCol) { //纵向移动时
                if (row > pRow) { //向下移动时
                    for (int i = pRow; i <= row; i++) {
                        if (curGrids[i][col] != 0) {
                            count++;
                        }
                    }
                }
                else if (row < pRow) { //向上移动时
                    for (int i = row; i <= pRow; i++) {
                        if (curGrids[i][col] != 0) {
                            count++;
                        }
                    }
                }
            }
            if (count != 1 && count != 3) { //count为1时说明路径上没有其它棋子，count为3时说明炮在隔山打牛
                return false;
            }
            if (count == 3 && curGrids[row][col] == 0) { //count为3时只能是吃子
                return false;
            }
            return generalMoveLimit(row, col, room, curGrids);
        }

        @Override
        public String getRecordName() {
            return mSide == 1 ? mName : "包";
        }
    }

    /**
     * 河中石
     */
    private static class Stone extends Chess {

        public Stone(int pRow, int pCol) {
            super("石", 7, pRow, pCol);
        }

        @Override
        public List<int[]> getCanMovedPos(MiniEternalChessRoom room, int[][] curGrids, List<Chess> chessList) {
            return null;
        }

        @Override
        public boolean isPosCanMove(int row, int col, MiniEternalChessRoom room, int[][] curGrids, List<Chess> chessList) {
            return false;
        }

        @Override
        public String getRecordName() {
            return mName;
        }
    }


}
